﻿namespace WinPRTValidations
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using Windows.UI;
    using System.Windows.Interactivity;

    public class TextBoxValidator : Behavior<TextBox>, INotifyPropertyChanged
    {
        private static DependencyProperty ValidateOnEventProperty = DependencyProperty.Register("ValidateOnEvent", typeof(ValidationEventEnum), typeof(TextBoxValidator), null);
        private static DependencyProperty ValidationPatternProperty = DependencyProperty.Register("ValidationPatternType", typeof(ValidationPatternEnum), typeof(TextBoxValidator), null);
        private static DependencyProperty RegExPatternProperty = DependencyProperty.Register("RegExPattern", typeof(string), typeof(TextBoxValidator), null);
        private static DependencyProperty ValidationFailedProperty = DependencyProperty.Register("ValidationFailed", typeof(bool), typeof(TextBoxValidator), null);

        public ValidationEventEnum ValidateOnEvent
        {
            get { return (ValidationEventEnum)this.GetValue(ValidateOnEventProperty); }
            set { this.SetValue(ValidateOnEventProperty, value); }
        }

        public ValidationPatternEnum ValidationPatternType
        {
            get { return (ValidationPatternEnum)this.GetValue(ValidationPatternProperty); }
            set { this.SetValue(ValidationPatternProperty, value); }
        }

        public string RegExPattern
        {
            get { return this.GetValue(RegExPatternProperty).ToString(); }
            set { this.SetValue(RegExPatternProperty, value); }
        }

        public bool ValidationFailed
        {
            get { return (bool)this.GetValue(ValidationFailedProperty); }
            set { this.SetValue(ValidationFailedProperty, value); }
        }

        public TextBoxValidator()
        {

        }

        protected override void OnAttached()
        {
            base.OnAttached();
            ValidationFailed = false;

            switch (ValidateOnEvent)
            {
                case ValidationEventEnum.LostFocus:
                    this.AssociatedObject.LostFocus += AssociatedObjectValidateGeneral;
                    break;
                case ValidationEventEnum.Loaded:
                    this.AssociatedObject.Loaded += AssociatedObjectValidateGeneral;
                    break;
                case ValidationEventEnum.TextChanged:
                    this.AssociatedObject.TextChanged += AssociatedObject_TextChanged;
                    break;
                case ValidationEventEnum.Tapped:
                    this.AssociatedObject.Tap += AssociatedObject_Tap;
                    break;
                case ValidationEventEnum.KeyDown:
                    this.AssociatedObject.KeyDown += AssociatedObjectValidateKey;
                    break;
                case ValidationEventEnum.KeyUp:
                    this.AssociatedObject.KeyUp += AssociatedObjectValidateKey;
                    break;
            }
        }

        void AssociatedObjectValidateKey(object sender, System.Windows.Input.KeyEventArgs e)
        {
            ValidateText();
        }

        void AssociatedObject_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            ValidateText();
        }

        private void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
        {
            ValidateText();
        }

        private void AssociatedObjectValidateGeneral(object sender, RoutedEventArgs e)
        {
            ValidateText();
        }

        private void ValidateText()
        {
            ValidationFailed = false;
            double number;
            switch (ValidationPatternType)
            {
                case ValidationPatternEnum.NotEmpty:
                    if (string.IsNullOrEmpty(this.AssociatedObject.Text))
                        ValidationFailed = true;
                    break;
                case ValidationPatternEnum.IsNumeric:
                    if (!double.TryParse(this.AssociatedObject.Text, out number))
                        ValidationFailed = true;
                    break;
                case ValidationPatternEnum.NotIsNumeric:
                    if (double.TryParse(this.AssociatedObject.Text, out number))
                        ValidationFailed = true;
                    break;
                case ValidationPatternEnum.RegExPattern:
                    if (!Regex.IsMatch(this.AssociatedObject.Text, RegExPattern))
                        ValidationFailed = true;
                    break;
                default:
                    break;
            }

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("ValidationFailed"));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
